# mqtt_web_listener.py
import paho.mqtt.client as mqtt
import json
import time
from datetime import datetime
from flask import Flask, render_template, jsonify, request
from flask_socketio import SocketIO, emit
import threading

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
socketio = SocketIO(app, cors_allowed_origins="*")


class MQTTWebListener:
    def __init__(self):
        # self.host = "172.20.10.10" #IP of cjy
        self.host = "192.168.232.53" #IP of wly
        self.port = 1883
        # self.username = "admin"  #MQTT username of cjy
        self.username = "admin"  #MQTT username of wly
        # self.password = "12345678" #MQTT password of cjy
        self.password = "wly" #MQTT password of wly
        self.messages = []  # 存储消息历史
        self.messages = []  # 存储消息历史
        self.client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)  # 使用新版 API
        self.setup_client()

    def setup_client(self):
        self.client.username_pw_set(self.username, self.password)
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.client.on_disconnect = self.on_disconnect

    def on_connect(self, client, userdata, flags, rc, properties=None):
        if rc == 0:
            print(f"✅ Connected to MQTT broker")
            client.subscribe("ID")
            client.subscribe("name")
            client.subscribe("mode")  # 新增订阅 mode 主题
            client.subscribe("speed")
            client.subscribe("status")  # 新增订阅 status 主题
            client.subscribe("#")  # 通配符订阅
            socketio.emit('mqtt_status', {'status': 'connected'})
        else:
            print(f"❌ Failed to connect, return code: {rc}")
            socketio.emit('mqtt_status', {'status': 'disconnected', 'error': rc})

    def on_message(self, client, userdata, msg):
        try:
            message_data = {
                'timestamp': datetime.now().isoformat(),
                'topic': msg.topic,
                'payload': msg.payload.decode('utf-8'),
                'qos': msg.qos,
                'retained': msg.retain
            }

            # 解析ID主题的心跳消息
            if msg.topic == "ID" and "heartbeat_" in message_data['payload']:
                self.parse_heartbeat(message_data['payload'])

            # 保存消息到历史记录
            self.messages.append(message_data)
            if len(self.messages) > 100:  # ��保留最近100条消息
                self.messages.pop(0)

            print(f"📨 {message_data['timestamp']} - {message_data['topic']}: {message_data['payload']}")

            # 实时推送到Web客户端
            socketio.emit('new_message', message_data)

        except Exception as e:
            print(f"❌ Error processing message: {e}")

    def parse_heartbeat(self, payload):
        """解析心跳消息格式: heartbeat_X_cmd_Y_speed_Z_mode_A_status_B_current_status_C_current_speed_D"""
        try:
            # 按下划线分割消息
            parts = payload.split('_')

            # 寻找current_status和current_speed的值
            current_status_value = None
            current_speed_value = None

            for i in range(len(parts)):
                if parts[i] == "current" and i + 1 < len(parts):
                    if parts[i + 1] == "status" and i + 2 < len(parts):
                        current_status_value = parts[i + 2]
                    elif parts[i + 1] == "speed" and i + 2 < len(parts):
                        current_speed_value = parts[i + 2]

            # 发送解析出的current_status
            if current_status_value is not None:
                status_message = {
                    'timestamp': datetime.now().isoformat(),
                    'topic': 'current_status',
                    'payload': current_status_value,
                    'qos': 1,
                    'retained': False
                }
                socketio.emit('new_message', status_message)
                print(f"📊 解析出当前状态: {current_status_value}")

            # 发送解析出的current_speed
            if current_speed_value is not None:
                speed_message = {
                    'timestamp': datetime.now().isoformat(),
                    'topic': 'current_speed',
                    'payload': current_speed_value,
                    'qos': 1,
                    'retained': False
                }
                socketio.emit('new_message', speed_message)
                print(f"📊 解析出当前速度: {current_speed_value}")


        except Exception as e:
            print(f"❌ 解析心跳消息失败: {e}")

    def on_disconnect(self, client, userdata, flags, rc, properties=None):
        print(f"🔌 Disconnected from MQTT broker")
        socketio.emit('mqtt_status', {'status': 'disconnected'})

    def start_mqtt(self):
        try:
            self.client.connect(self.host, self.port, 60)
            self.client.loop_start()
        except Exception as e:
            print(f"❌ MQTT connection error: {e}")

    def publish_message(self, topic, message):
        """发布消息到MQTT"""
        try:
            self.client.publish(topic, message)
            return True
        except Exception as e:
            print(f"❌ Publish error: {e}")
            return False


# 创建全局MQTT监听器实例
mqtt_listener = MQTTWebListener()


@app.route('/')
def index():
    return render_template('mqtt_monitor.html')


@app.route('/api/messages')
def get_messages():
    """获取消息历史"""
    return jsonify(mqtt_listener.messages)


@app.route('/api/publish', methods=['POST'])
def publish_message():
    """发布消息"""
    data = request.get_json()
    topic = data.get('topic')
    message = data.get('message')

    if mqtt_listener.publish_message(topic, message):
        return jsonify({'status': 'success'})
    else:
        return jsonify({'status': 'error'}), 500


@socketio.on('connect')
def handle_connect():
    print('👤 Client connected to WebSocket')
    emit('mqtt_status', {'status': 'connected' if mqtt_listener.client.is_connected() else 'disconnected'})


@socketio.on('disconnect')
def handle_disconnect():
    print('👤 Client disconnected from WebSocket')


if __name__ == '__main__':
    # 在单独线程中启动MQTT监听器
    mqtt_thread = threading.Thread(target=mqtt_listener.start_mqtt)
    mqtt_thread.daemon = True
    mqtt_thread.start()

    # 启动Web服务器
    print("🌐 Starting web server at http://localhost:8080")
    socketio.run(app, debug=True, host='0.0.0.0', port=8080, allow_unsafe_werkzeug=True)